import {
  defineComponent,
  ref,
  reactive,
  getCurrentInstance,
  onMounted,
  watch,
  computed,
} from 'vue'

import {
  ElDialog as Dialog,
  ElButton as Button,
  ElForm as Form,
  ElFormItem as FormItem,
  ElInput as Input,
  ElSelect as Select,
  ElOption as Option,
  ElDatePicker as DatePicker,
  ElRadioGroup as RadioGroup,
  ElRadio as Radio,
  ElCheckboxGroup as CheckboxGroup,
  ElCheckbox as Checkbox,
  ElSwitch as Switch,
  ElInputNumber as InputNumber,
  ElTree as Tree,
  ElIcon as Icon,
} from 'element-plus'
import { isJSON } from '@/utils'
import { useI18n } from 'vue-i18n'
export default defineComponent({
  name: 'SDialog',
  props: {
    draggable: {
      type: Boolean,
      default: false,
      required: false,
    },
    width: {
      type: String,
      required: false,
      default: '520px',
    },
    closeOnClickModal: {
      type: Boolean,
      required: false,
      default: true,
    },
    alignCenter: {
      type: Boolean,
      required: false,
      default: true,
    },
    showClose: {
      type: Boolean,
      required: false,
      default: false,
    },
    destroyOnClose: {
      type: Boolean,
      required: false,
      default: false,
    },
    appendToBody: {
      type: Boolean,
      required: false,
      default: false,
    },
  },
  setup (props, { attrs, slots, emit, expose }) {
    const { t } = useI18n();
    const { dialogConfig, formConfig, formItemConfig, ...$listener } = attrs;

    const { dialogVisible: delDialogVisible, ...$otherDialogConfig } = dialogConfig;

    const dialogVisible = computed(() => dialogConfig.dialogVisible)

    let formInline = formConfig.formInline
    formConfig.size = formConfig?.size ?? 'default'
    formConfig.labelWidth = formConfig?.labelWidth ?? 'auto'
    formConfig.class = formConfig?.class ?? ''


    const formList = formItemConfig.formList

    const handleClose = () => {
      dialogConfig.beforeClose()
    }
    let formInstance = ref('')
    onMounted(() => {
      formInstance.value = getCurrentInstance()
    })
    const loading = ref(false)
    const handleSubmit = () => {
      loading.value = true
      emit('handleSubmit', formInstance.value.ctx.$refs.formRef, loading)
    }
    const handleCheck = (model) => {
      return (checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys) => {
        formInline[model] = checkedKeys.checkedKeys
      }
    }
    const resetForm = (formEl) => {
      if (!formEl) return
      formEl.clearValidate()

      Object.keys(formInline).map((key) => {
        formInline[key] = undefined
      })
    }
    watch(dialogConfig, (newValue, oldValue) => {
      if (newValue.dialogVisible === false) {
        resetForm(formInstance.value.ctx.$refs.formRef)
      }
    })

    const fcts = reactive({
      input ({ fct, props, model }) {
        return <Input {...props} v-model={formInline[model]} />
      },
      textarea ({ fct, props, model }) {
        return <Input type="textarea" {...props} v-model={formInline[model]} />
      },
      inputNumber ({ fct, props, model }) {
        return <InputNumber {...props} v-model={formInline[model]} />
      },
      tree ({ fct, props, model }) {
        return <Tree {...props} onCheck={handleCheck(model)} />
      },
      select ({ fct, props, model }) {
        const { options, ...other } = props
        const $props = { ...other }
        return (
          <Select {...$props} v-model={formInline[model]}>
            {options?.map((item, index) => (
              <Option key={index} label={item.label} value={item.value} />
            ))}
          </Select>
        )
      },
      switch ({ fct, props, model }) {
        const { ...other } = props
        const $props = { ...other }
        return <Switch {...$props} v-model={formInline[model]} />
      },
      date ({ fct, props, model }) {
        const { type } = fct
        const $props = {
          type,
          ...props,
        }
        return <DatePicker {...$props} v-model={formInline[model]} />
      },
      datetime ({ fct, props, model }) {
        const { type } = fct
        const $props = {
          type,
          ...props,
        }
        return <DatePicker {...$props} v-model={formInline[model]} />
      },
      radio ({ fct, props, model }) {
        const { options, ...other } = props
        const $props = { ...other }
        return (
          <RadioGroup {...$props} v-model={formInline[model]}>
            {options?.map((item) => (
              <Radio label={item.value}>{item.label}</Radio>
            ))}
          </RadioGroup>
        )
      },

      checkbox ({ fct, props, model }) {
        const { options, ...other } = props
        const $props = { ...other }
        return (
          <CheckboxGroup {...$props} v-model={formInline[model]}>
            {options?.map((item) => (
              <Checkbox label={item} />
            ))}
          </CheckboxGroup>
        )
      },
    })
    const renderFormItem = () => {
      const index = formList.findIndex((item) => item.type === 'langs')
      let path;
      if (index >= 0) {
        path = (formList.splice(index, 1)?.[0] ?? {})?.path
      }

      return formList.map((item) => {
        const { fct, ...fitem } = item;
        const { model, type, ...other } = fct;

        if (model && path) {
          item.label = t(`${path}.${model}`)
          const { rules } = item

          if (rules) {
            const ruleIndex = rules.findIndex(
              (ruleItem) => 'message' in ruleItem
            )
            if (ruleIndex >= 0) {
              rules[ruleIndex].message = t(`${path}.${model + 'Tips'}`)
            }
          }

          if (fct.placeholder) {
            fct.placeholder = t(`${path}.${model + 'Tips'}`)
          }

          const { options: fctOptions } = fct
          const options = isJSON(t(`${path}.${model + 'Options'}`))
            ? JSON.parse(t(`${path}.${model + 'Options'}`))
            : false
          if (fctOptions && options) {
            fctOptions.forEach((fctItem, fctIndex) => {
              if (['radio', 'select'].includes(type)) {
                fctItem.label = options[fctIndex]
              }

              if (['checkbox'].includes(type)) {
                fctOptions[fctIndex] = options[fctIndex]
              }
            })
          }
        }
        const props = { ...other }
        const FORM_DOM = fcts[type]({ fct, props, model })
        return <FormItem {...fitem}>{FORM_DOM}</FormItem>
      })
    }
    const renderForm = (formConfig) => {
      const { formInline, ...other } = formConfig
      const $props = { ...other }
      return (
        <>
          <Form {...$props} model={formInline}>
            {renderFormItem()}
            {slots['extra'] ? slots['extra']() : null}
          </Form>
        </>
      )
    }

    const $slots = {
      header: () => (
        <>
          <div class="header">
            <span class="title">{formItemConfig.title}</span>
            <i class={['iconfont icon-guanbi1 icon']} onClick={handleClose}></i>
          </div>
        </>
      ),
      footer: () => (
        <>
          <footer>
            <span>
              <Button
                v-slots={{
                  icon: () => (
                    <Icon>
                      {{
                        default: () => <svg-icon name="取消"></svg-icon>,
                      }}
                    </Icon>
                  ),
                }}
                onClick={handleClose}
              >
                {t('dialog.cancel')}
              </Button>

              {/* 写法1 */}
              <Button
                loading={loading.value}
                type="primary"
                onClick={handleSubmit}
                v-slots={{
                  icon: () => (
                    <Icon>
                      {{
                        default: () => <svg-icon name="提交"></svg-icon>,
                      }}
                    </Icon>
                  ),
                }}
              >
                {t('dialog.submit')}
              </Button>
              {/* 写法2 */}
              {/* <Button
                loading={loading.value}
                type="primary"
                onClick={handleSubmit}
              >
                {{
                  default: () => t('dialog.submit'),
                  icon: () => (
                    <Icon>
                      {{
                        default: () => <svg-icon name="提交"></svg-icon>,
                      }}
                    </Icon>
                  ),
                }}
              </Button> */}
            </span>
          </footer>
        </>
      ),
    }
    const $props = {
      ...props,
      ...$listener,
      ...$otherDialogConfig,
    }
    return () => (
      <>
        <Dialog

          v-model={dialogVisible.value} v-slots={$slots} {...$props}>
          {renderForm(formConfig)}
        </Dialog>
      </>
    )
  },
  install: function (Vue) {
    Vue.component(this.name, this)
  },
});